package com.base.common.db;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

import com.base.common.util.StringUtils;
import com.base.common.util.log.LogUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  数据库操作Provider与表匹配
 */
public class DBContentProvider extends ContentProvider {
	private static final String LOG_TAG = "DBContentProvider";
	public final static byte[] _writeLock = new byte[0];
	private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

	private static Map<Uri, String> vndDirs = null;

	private static Map<Uri, String> vndItems = null;

	private DBHelper dbHelper;

	public DBContentProvider() {
		// LogUtil.e(LOG_TAG, "DBContentProvider 构造方法");
	}

	static {
		init();
	}

	/**
	 * 初始化UriMatcher和Uri对应的MINI类型
	 */
	private static void init() {

		try {
			vndDirs = new HashMap<Uri, String>();
			vndItems = new HashMap<Uri, String>();

			int index = 1;

			String protocol = DBConstants.ContentProvider.PROTOCOL;
			String authority = DBConstants.ContentProvider.AUTHORITY;
			String dir = DBConstants.ContentProvider.DIR;
			String item = DBConstants.ContentProvider.ITEM;

			for (String table : DBConstants.ShopDB.TABLES_STRINGS) {
				/**
				 * 所有表与Uri对应关系
				 */
				Uri uri = Uri.parse(protocol + authority + "/" + table);

				/**
				 * 所有MINI类型
				 */
				vndDirs.put(uri, dir + table);
				vndItems.put(uri, item + table);

				/**
				 * UriMatcher 相关
				 */
				uriMatcher.addURI(DBConstants.ContentProvider.AUTHORITY, table,
						index);
				index++;
				uriMatcher.addURI(DBConstants.ContentProvider.AUTHORITY, table
						+ "/#", index);
				index++;
			}
		} catch (Exception e) {
			LogUtil.e(LOG_TAG, StringUtils.getExceptionMsg(e));
		}
	}

	/**
	 * 删除数据
	 * 
	 * @param uri
	 *            Uri
	 * @param selection
	 *            删除条件
	 * @param selectionArgs
	 *            条件参数
	 * @return
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		synchronized (_writeLock) {
			SQLiteDatabase wdb = dbHelper.getWritableDatabase();
			String table = getTableName(uri);
			int count = wdb.delete(table, selection, selectionArgs);
			//wdb.close();
			getContext().getContentResolver().notifyChange(uri, null);
			return count;
		}
	}

	/**
	 * 获取MINI类型
	 * 
	 * @param uri
	 * @return
	 */
	@Override
	public synchronized String getType(Uri uri) {
		int type = uriMatcher.match(uri);
		if (type % 2 == 0) {// 带有ID 返回单记录
			return vndItems.get(uri);
		} else {// 根URI 返回多记录
			return vndDirs.get(uri);
		}
	}

	/**
	 * 插入数据
	 * 
	 * @param uri
	 * @param values
	 * @return
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		synchronized (_writeLock) {
			SQLiteDatabase wdb = dbHelper.getWritableDatabase();
			String table = getTableName(uri);
			long rowId = wdb.insert(table, null, values);
			//wdb.close();
			if (rowId > 0) {
				Uri muri = ContentUris.withAppendedId(uri, rowId);
				getContext().getContentResolver().notifyChange(muri, null);
				return muri;
			}
			return uri;
		}
	}

	/**
	 * @return
	 */
	@Override
	public boolean onCreate() {
		LogUtil.i(LOG_TAG, "DBContentProvider onCreate ...");
		/**
		 * 初始化数据库和数据表
		 */
		dbHelper =  DBHelper.getInstance(getContext());
		return true;
	}

	/**
	 * 查询
	 * 
	 * @param uri
	 * @param projection
	 * @param tempSelection
	 * @param selectionArgs
	 * @param sortOrder
	 * @return
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		synchronized (_writeLock) {

			SQLiteDatabase sdb = dbHelper.getReadableDatabase();
			/**
			 * 约定如果selection以sql://开头，则为SQL语句查询
			 */
			Cursor cursor = null;
			String prefix = "sql://";
			String tempSelection = selection;
			if (tempSelection != null && tempSelection.startsWith(prefix)) {
				String sql = tempSelection.substring(tempSelection
						.indexOf(prefix)
						+ prefix.length());
				cursor = sdb.rawQuery(sql, null);
			} else {// Uri
				/**
				 * 查询参数设置
				 */
				SQLiteQueryBuilder sqb = new SQLiteQueryBuilder();
				String table = getTableName(uri);
				sqb.setTables(table);

				Long id = getQueryId(uri);
				if (id != null) {// 如果带有ID
					tempSelection = "id="
							+ id
							+ (TextUtils.isEmpty(tempSelection) ? "" : " and ("
									+ tempSelection + ")");
				}

				cursor = sqb.query(sdb, projection, tempSelection,
						selectionArgs, null, null, sortOrder);
			}
			// cursor.setNotificationUri(getContext().getContentResolver(),
			// uri);// Register
			// to
			// watch
			// a
			// content
			// URI
			// for
			// changes
			return cursor;
		}

	}

	/**
	 * 修改
	 * 
	 * @param uri
	 * @param values
	 * @param selection
	 * @param selectionArgs
	 * @return
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		synchronized (_writeLock) {
			SQLiteDatabase wdb = dbHelper.getWritableDatabase();

			String table = getTableName(uri);

			int count = 0;
			Long id = getQueryId(uri);
			if (id != null) {
				count = wdb.update(table, values, "id="
						+ id
						+ (TextUtils.isEmpty(selection) ? "" : " and ("
								+ selection + ")"), selectionArgs);
			} else {
				count = wdb.update(table, values, selection, selectionArgs);
			}
			//wdb.close();
			if (count > 0) {
				getContext().getContentResolver().notifyChange(uri, null);
			}
			return count;
		}
	}

	/**
	 * 从Uri中获取表名(注：Uri必须有规则 content://com.example/表名[/ID])
	 */
	private String getTableName(Uri uri) {
		if (uri == null) {
			return null;
		}

		String table = null;
		List<String> segments = uri.getPathSegments();
		if (segments.size() > 0) {
			table = segments.get(0);
		}

		return table;
	}

	/**
	 * 获得Uri中的ID部分
	 */
	private Long getQueryId(Uri uri) {
		if (uri == null) {
			return null;
		}

		List<String> segments = uri.getPathSegments();
		if (segments.size() > 1) {
			String strId = segments.get(1);
			try {
				return Long.parseLong(strId);// ID
			} catch (NumberFormatException e) {
				LogUtil.e(LOG_TAG, StringUtils.getExceptionMsg(e));
				return null;
			}
		}
		return null;
	}

}
